package com.ygqh.baby.model;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author: sunshuo
 * @Date: 2019/9/9/009 17:25
 * @Version: 1.0
 */
public class UserCountWrapper {

    private Date startDate;

    private Date endDate;

    private List<Long> newUserList;

    private List<Long> oldUserList;

    private List<Long> pbNewUserList;

    private List<Long> pbOldUserList;

    private UserCountWrapper next;

    public UserCountWrapper(Date startDate, Date endDate) {
        this.startDate = startDate;
        this.endDate = endDate;
        this.newUserList = new ArrayList<>();
        this.oldUserList = new ArrayList<>();
        this.pbNewUserList = new ArrayList<>();
        this.pbOldUserList = new ArrayList<>();
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public boolean validate(Date time) {
        return !time.before(startDate) || !time.after(endDate);
    }

    private void addNewUser(Long userId) {
        this.newUserList.add(userId);
    }

    private void addOldUser(Long userId) {
        this.oldUserList.add(userId);
    }

    public void addUser(Date paidTime, Long userId, boolean newCustom) {
        if (this.validate(paidTime)) {
            this.addUser(userId, newCustom);
        } else if (this.next != null) {
            this.next.addUser(paidTime, userId, newCustom);
        }
    }

    private void addUser(Long userId, boolean newCustom) {
        if (newCustom) {
            addNewUser(userId);
        } else {
            addOldUser(userId);
        }
    }

    public UserCountWrapper getNext() {
        return next;
    }

    public void setNext(UserCountWrapper next) {
        this.next = next;
    }

    public List<UserCountModel> getUserCountModel() {
        List<UserCountModel> modelList = new ArrayList<>();
        buildModel(modelList, null, null);
        return modelList;
    }

    private void buildModel(List<UserCountModel> modelList, List<Long> prevNewUser, List<Long> prevOldUser) {
        if (CollectionUtils.isNotEmpty(prevNewUser) || CollectionUtils.isNotEmpty(prevOldUser)) {
            oldUserList.forEach(oldUser -> {
                if (CollectionUtils.isNotEmpty(prevNewUser) && prevNewUser.contains(oldUser)) {
                    pbNewUserList.add(oldUser);
                } else if (CollectionUtils.isNotEmpty(prevOldUser) && prevOldUser.contains(oldUser)) {
                    pbOldUserList.add(oldUser);
                }
            });
        }
        BigDecimal pbNewUserRate = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(prevNewUser)) {
            pbNewUserRate = BigDecimal.valueOf(pbNewUserList.size()).
                    divide(BigDecimal.valueOf(prevNewUser.size()), 2, BigDecimal.ROUND_DOWN);
        }
        BigDecimal pbOldUserRate = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(prevOldUser)) {
            pbOldUserRate = BigDecimal.valueOf(pbOldUserList.size()).
                    divide(BigDecimal.valueOf(prevOldUser.size()), 2, BigDecimal.ROUND_DOWN);
        }
        modelList.add(new UserCountModel(startDate, endDate, newUserList.size(), oldUserList.size(), pbNewUserList.size(),
                pbOldUserList.size(), pbNewUserRate, pbOldUserRate));
        if (this.next != null) {
            this.next.buildModel(modelList, this.newUserList, this.oldUserList);
        }
    }

    public static class UserCountModel {

        private Date startDate;

        private Date endDate;

        private int newUserCount;

        private int oldUserCount;

        private int pbNewUserCount;

        private int pbOldUserCount;

        private BigDecimal pbNewUserRate;

        private BigDecimal pbOldUserRate;

        private UserCountModel(Date startDate, Date endDate, int newUserCount, int oldUserCount, int pbNewUserCount,
                               int pbOldUserCount, BigDecimal pbNewUserRate, BigDecimal pbOldUserRate) {
            this.startDate = startDate;
            this.endDate = endDate;
            this.newUserCount = newUserCount;
            this.oldUserCount = oldUserCount;
            this.pbNewUserCount = pbNewUserCount;
            this.pbOldUserCount = pbOldUserCount;
            this.pbNewUserRate = pbNewUserRate;
            this.pbOldUserRate = pbOldUserRate;
        }

        public Date getStartDate() {
            return startDate;
        }

        public Date getEndDate() {
            return endDate;
        }

        public int getNewUserCount() {
            return newUserCount;
        }

        public int getOldUserCount() {
            return oldUserCount;
        }

        public int getPbNewUserCount() {
            return pbNewUserCount;
        }

        public int getPbOldUserCount() {
            return pbOldUserCount;
        }

        public BigDecimal getPbNewUserRate() {
            return pbNewUserRate;
        }

        public BigDecimal getPbOldUserRate() {
            return pbOldUserRate;
        }

        public String getKey() {
            return startDate == null ? null : DateFormatUtils.format(startDate, "MM.dd");
        }
    }
}
